package com.idealighter.game.web.checklevel.shuihu.xml;

import com.google.common.collect.LinkedListMultimap;
import com.google.inject.Singleton;
import com.idealighter.game.games.shuihu.common.BonusInnerCfgTypeConstant;
import com.idealighter.game.games.shuihu.struct.ShuiHuSeat;
import com.idealighter.game.web.checklevel.shuihu.service.ShuiHuBasicControlCheck.IdCount;
import com.idealighter.utils.check.EmptyUtil;
import com.idealighter.utils.code.RandCodeUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import lombok.Data;

@Singleton
public class ShuiHuXmlControlCheck {
  // private static final Logger LOG = LoggerFactory.getLogger(ShuiHuXmlControlCheck.class);
  private static List<Long> betList = new ArrayList<Long>();
  private static List<Integer> bonusList = new ArrayList<Integer>();
  // 小玛丽退出图标
  public static final int BONUS_EXIT_ICON = 9;

  static {
    betList.add(10L);
    betList.add(20L);
    betList.add(50L);
    betList.add(100L);
    // betList.add(20000);
    // betList.add(50000);

    bonusList.add(1);
    bonusList.add(2);
    bonusList.add(3);
  }

  /**
   * @Title checkXml.
   * @Description 校验xml
   * @return .
   */
  public ShuihuBonusCheckResult checkXml(int betCount, ShuiHuBonusIconGroup iconGroup,
      ShuiHuBonusInnerGroup innerGroup, ShuiHuBonusOuterGroup outerGroup) {
    ShuihuBonusCheckResult result = new ShuihuBonusCheckResult();
    for (int count = 0; count < betCount; count++) {
      ShuiHuSeat seat = new ShuiHuSeat((byte) 0, null);
      seat.setBonus(1); // 设置bonus数量为1
      seat.setBet(RandCodeUtil.randomList(betList));
      result.addBetCount(1L);
      result.addBetChips(seat.getBet());

      ShuihuBonusCheckResult itemResult = new ShuihuBonusCheckResult();
      while (seat.getBonus() > 0) {
        ShuihuBonusCheckResult checkResult = doCheck(seat, iconGroup, innerGroup, outerGroup);

        itemResult.addFourCount(checkResult.getFourCount());
        itemResult.addThreeCount(checkResult.getThreeCount());
        itemResult.addTypeMap(checkResult.getTypeMap());
        itemResult.addWinChips(checkResult.getWinChips());
        itemResult.addRoundCount(checkResult.getRoundCount());
      }

      result.addBetChips(itemResult.getBetChips());
      if (itemResult.winChips > 0L) {
        result.addWinChips(itemResult.getWinChips());
        result.addWinCount(1L);
      }

      result.addFourCount(itemResult.getFourCount());
      result.addThreeCount(itemResult.getThreeCount());
      result.addTypeMap(itemResult.getTypeMap());
      result.addRoundCount(itemResult.getRoundCount());

      itemResult = null;
    }
    return result;
  }

  private ShuihuBonusCheckResult doCheck(ShuiHuSeat seat, ShuiHuBonusIconGroup bonusIcons,
      ShuiHuBonusInnerGroup innerGroup, ShuiHuBonusOuterGroup outerGroup) {
    ShuihuBonusCheckResult result = new ShuihuBonusCheckResult();
    result.addRoundCount(1); //
    int insideIcon = 0;
    /*
     * 随机内部图标(4个),使用LinkedListMultimap方便计算 .
     */
    LinkedListMultimap<Integer, Integer> insideIcons = LinkedListMultimap.create();
    insideIcons.put(insideIcon = RandCodeUtil.random(1, 8), insideIcon);
    insideIcons.put(insideIcon = RandCodeUtil.random(1, 8), insideIcon);
    insideIcons.put(insideIcon = RandCodeUtil.random(1, 8), insideIcon);
    insideIcons.put(insideIcon = RandCodeUtil.random(1, 8), insideIcon);


    // 内圈图标kickOut
    kickOutInnerIcons(insideIcons, innerGroup, insideIcon);

    /*
     * 随机外部图标 .
     */
    // 外部图标
    int outsideIcon = 0;
    // 外部图标合计权重
    int totalWeight = bonusIcons.getTotalWeight() + seat.getXiaoMaLiTotalWeightChange();
    // 随机数
    int rand = RandCodeUtil.random(totalWeight);
    int sum = 0;

    for (int i = 0; i < bonusIcons.getList().size(); i++) {
      ShuiHuBonusIconInput bonusIconDomain = bonusIcons.getList().get(i);
      // 权重变化
      Integer weightChange = seat.getXiaoMaLiWeightChangeMap().get(bonusIconDomain.getIconId());
      if (weightChange == null) {
        weightChange = 0;
        seat.getXiaoMaLiWeightChangeMap().put(bonusIconDomain.getIconId(), weightChange);
      }

      // 剩余的权重
      int leftWeight = bonusIconDomain.getWeight() + weightChange;
      if (leftWeight < 0) {
        leftWeight = 0;
      }
      sum += leftWeight;
      if (rand < sum) {
        outsideIcon = bonusIconDomain.getIconId();
        // 执行kickOut
        ShuiHuBonusOuterInput outerKickOutDomain = outerGroup.getMap().get(outsideIcon);

        int kickOut = outerKickOutDomain.getKickOut();
        int kickOutMax = outerKickOutDomain.getKickOutMax();
        if (RandCodeUtil.random(kickOutMax) <= kickOut) {
          if (i < bonusIcons.getList().size() - 1) {
            outsideIcon = bonusIcons.getList().get(i + 1).getIconId();
          } else {
            outsideIcon = bonusIcons.getList().get(0).getIconId();
          }
        }
        break;
      }
    }

    // 增加/减少权重
    int totalChange = 0;
    for (int i = 0; i < bonusIcons.getList().size(); i++) {
      ShuiHuBonusIconInput bonusIconDomain = bonusIcons.getList().get(i);
      // 获取已经变化的权重
      Integer weightChange = seat.getXiaoMaLiWeightChangeMap().get(bonusIconDomain.getIconId());
      if (weightChange == null) {
        weightChange = 0;
      }
      // 图标剩余的权重
      int leftWeight =
          bonusIconDomain.getWeight() + weightChange + bonusIconDomain.getWeightChange();
      int change = 0;
      if (leftWeight < 0) {
        change -= bonusIconDomain.getWeight();
      } else {
        change = weightChange + bonusIconDomain.getWeightChange();
      }
      totalChange += change;
      seat.getXiaoMaLiWeightChangeMap().put(bonusIconDomain.getIconId(), change);
    }
    seat.setXiaoMaLiTotalWeightChange(totalChange);

    long winChips = 0;
    if (outsideIcon == BONUS_EXIT_ICON) {
      seat.setBonus(seat.getBonus() - 1);
      // 每次bonus重置权重配置
      seat.setXiaoMaLiWeightChangeMap(new ConcurrentHashMap<Integer, Integer>());
      seat.setXiaoMaLiTotalWeightChange(0);
    } else {
      int multiple = 0;

      // 内部图标是否中奖
      if (insideIcons.keySet().size() == 1) {
        // 四连线
        ShuiHuBonusInnerInput innerCfgDomain =
            innerGroup.getMap().get(BonusInnerCfgTypeConstant.FOUR_ICON);
        multiple += innerCfgDomain.getRate();
        result.addFourCount(1);
      } else if (insideIcons.keySet().size() == 2 && (insideIcons.get(insideIcon).size() == 1
          || insideIcons.get(insideIcon).size() == 3)) {
        // 三连线
        ShuiHuBonusInnerInput innerCfgDomain =
            innerGroup.getMap().get(BonusInnerCfgTypeConstant.THREE_ICON);
        multiple += innerCfgDomain.getRate();
        result.addThreeCount(1);
      }

      // 外面是否中奖
      if (insideIcons.keySet().contains(outsideIcon)) {
        multiple +=
            bonusIcons.getMap().get(outsideIcon).getRate() * insideIcons.get(outsideIcon).size();

        result.getTypeMap().put(outsideIcon, 1L);
      }

      // win = 内部中奖 + 外部图标中奖
      winChips = multiple * seat.getBet();
      seat.setBillChips(seat.getBillChips() + winChips);
    }

    result.setWinChips(winChips);

    return result;
  }

  private void kickOutInnerIcons(LinkedListMultimap<Integer, Integer> insideIcons,
      ShuiHuBonusInnerGroup innerGroup, int insideIcon) {
    int type = 0;
    int removeIcon = 0;
    if (insideIcons.keySet().size() == 1) {
      type = BonusInnerCfgTypeConstant.FOUR_ICON; // 图标四连线
      removeIcon = insideIcon;
    } else if (insideIcons.keySet().size() == 2) {

      if (insideIcons.get(insideIcon).size() == 1) {
        // 左三连线
        type = BonusInnerCfgTypeConstant.THREE_ICON; // 图标三连线
        Set<Integer> set = insideIcons.keySet();
        for (Iterator<Integer> iterator = set.iterator(); iterator.hasNext();) {
          int key = iterator.next();
          if (key != insideIcon) {
            removeIcon = key;
            break;
          }
        }
      } else if (insideIcons.get(insideIcon).size() == 3) {
        // 右三连线
        type = BonusInnerCfgTypeConstant.THREE_ICON; // 图标三连线
        removeIcon = insideIcon;
      }
    }

    if (type == BonusInnerCfgTypeConstant.FOUR_ICON
        || type == BonusInnerCfgTypeConstant.THREE_ICON) {
      // 获取内圈配置
      ShuiHuBonusInnerInput innerCfgDomain = innerGroup.getMap().get(type);
      int kickOut = innerCfgDomain.getKickOut();
      int kickOutMax = innerCfgDomain.getKickOutMax();
      // kick-out
      if (RandCodeUtil.random(kickOutMax) <= kickOut) {
        insideIcons.remove(removeIcon, removeIcon); // 移除一个(连线中的任何一个图标)
        insideIcons.put(insideIcon = RandCodeUtil.random(1, 8), insideIcon);
      }
    }
  }

  public static class ShuiHuBonusIconGroup {
    private int totalWeight = 0;
    private List<ShuiHuBonusIconInput> list = new ArrayList<ShuiHuBonusIconInput>();
    private Map<Integer, ShuiHuBonusIconInput> map;

    /**
     * 构造函数.
     */
    public ShuiHuBonusIconGroup(List<ShuiHuBonusIconInput> list) {
      map = new HashMap<Integer, ShuiHuBonusIconInput>();
      for (ShuiHuBonusIconInput item : list) {
        this.totalWeight += item.getWeight();
        map.put(item.getIconId(), item);
        this.list.add(item);
      }
    }

    public int getTotalWeight() {
      return totalWeight;
    }

    public List<ShuiHuBonusIconInput> getList() {
      return list;
    }

    public Map<Integer, ShuiHuBonusIconInput> getMap() {
      return map;
    }
  }

  public static class ShuiHuBonusInnerGroup {
    private List<ShuiHuBonusInnerInput> list = new ArrayList<ShuiHuBonusInnerInput>();
    private Map<Integer, ShuiHuBonusInnerInput> map;

    /**
     * 构造函数.
     */
    public ShuiHuBonusInnerGroup(List<ShuiHuBonusInnerInput> list) {
      map = new HashMap<Integer, ShuiHuBonusInnerInput>();
      for (ShuiHuBonusInnerInput item : list) {
        map.put(item.getType(), item);
        this.list.add(item);
      }
    }

    public List<ShuiHuBonusInnerInput> getList() {
      return list;
    }

    public Map<Integer, ShuiHuBonusInnerInput> getMap() {
      return map;
    }
  }

  public static class ShuiHuBonusOuterGroup {
    private List<ShuiHuBonusOuterInput> list = new ArrayList<ShuiHuBonusOuterInput>();
    private Map<Integer, ShuiHuBonusOuterInput> map;

    /**
     * 构造函数.
     */
    public ShuiHuBonusOuterGroup(List<ShuiHuBonusOuterInput> list) {
      map = new HashMap<Integer, ShuiHuBonusOuterInput>();
      for (ShuiHuBonusOuterInput item : list) {
        map.put(item.getIconId(), item);
        this.list.add(item);
      }
    }

    public List<ShuiHuBonusOuterInput> getList() {
      return list;
    }

    public Map<Integer, ShuiHuBonusOuterInput> getMap() {
      return map;
    }
  }

  @Data
  public static class ShuiHuBonusIconInput {
    private int iconId;
    private int rate;
    private int weight;
    private int weightChange;
  }

  @Data
  public static class ShuiHuBonusInnerInput {
    private int type;
    private int rate;
    private int kickOut;
    private int kickOutMax;
  }

  @Data
  public static class ShuiHuBonusOuterInput {
    private int iconId;
    private int kickOut;
    private int kickOutMax;
  }

  /**
   * @Title bo2dto.
   */
  public static ShuihuBonusCheckResultDto bo2dto(ShuihuBonusCheckResult bo) {
    ShuihuBonusCheckResultDto result = null;
    if (bo != null) {
      result = new ShuihuBonusCheckResultDto();
      result.setWinChips(bo.getWinChips());
      result.setThreeCount(bo.getThreeCount());
      result.setFourCount(bo.getFourCount());
      result.setBetCount(bo.getBetCount());
      result.setBetChips(bo.getBetChips());
      result.setRoundCount(bo.getRoundCount());
      result.setWinCount(bo.getWinCount());

      List<IdCount> list = new ArrayList<IdCount>();
      for (int id : bo.getTypeMap().keySet()) {
        Long count = bo.getTypeMap().get(id);
        IdCount item = new IdCount();
        item.setId(id);
        item.setCount(count);
        list.add(item);
      }
      result.setTypeList(list);
    }
    return result;
  }

  /**
   * @Title bo2dto.
   */
  public static List<ShuihuBonusCheckResultDto> bo2dto(List<ShuihuBonusCheckResult> list) {
    List<ShuihuBonusCheckResultDto> resultList = null;
    if (EmptyUtil.listIsNotEmpty(list)) {
      resultList = new ArrayList<ShuihuBonusCheckResultDto>();
      for (ShuihuBonusCheckResult item : list) {
        ShuihuBonusCheckResultDto resultItem = new ShuihuBonusCheckResultDto();
        resultItem = bo2dto(item);
        resultList.add(resultItem);
      }
    }
    return resultList;
  }

  @Data
  public static class ShuihuBonusCheckResultDto {
    private long betChips = 0L; // 下注金额
    private long winChips = 0L; // 赢的金币
    private long threeCount = 0L; // 三连线数量
    private long fourCount = 0L; // 四连线数量
    private List<IdCount> typeList = new ArrayList<IdCount>(); // 图标中奖信息
    private long betCount = 0L; // 下注次数
    private long roundCount = 0L; //
    private long winCount = 0L; // 赢的把数
  }

  @Data
  public class ShuihuBonusCheckResult {
    private long betChips = 0L; // 下注金额
    private long winChips = 0L; // 赢的金币
    private long threeCount = 0L; // 三连线数量
    private long fourCount = 0L; // 四连线数量
    private Map<Integer, Long> typeMap = new HashMap<Integer, Long>(); // 图标中奖信息
    private long betCount = 0L; // 下注次数
    private long roundCount = 0L; //
    private long winCount = 0L; // 赢的把数

    public void addBetChips(long betChips) {
      this.betChips += betChips;
    }

    public void addWinChips(long winChips) {
      this.winChips += winChips;
    }

    public void addThreeCount(long threeChips) {
      this.threeCount += threeChips;
    }

    public void addFourCount(long fourCount) {
      this.fourCount += fourCount;
    }

    /**
     * @Title addTypeMap.
     */
    public void addTypeMap(Map<Integer, Long> typeMap) {
      for (Integer key : typeMap.keySet()) {
        Long value = typeMap.get(key);
        Long oldValue = this.typeMap.get(key);
        if (oldValue == null) {
          oldValue = 0L;
        }
        this.typeMap.put(key, value + oldValue);
      }
    }

    public void addBetCount(long betCount) {
      this.betCount += betCount;
    }

    public void addRoundCount(long roundCount) {
      this.roundCount += roundCount;
    }

    public void addWinCount(long winCount) {
      this.winCount += winCount;
    }

  }
}
